use std::error::Error;
use std::ptr;

// pub struct Config {}

#[derive(Debug)]
pub struct LinkedList<T>
where
    T: std::fmt::Display + std::fmt::Debug,
{
    pub value: T,
    pub next: *mut LinkedList<T>,
}

trait DebuggableList {
    fn print_list(&mut self);
}

impl<T> LinkedList<T>
where
    T: std::fmt::Display + std::fmt::Debug,
{
    pub fn create<Iter>(iter: Iter) -> *mut LinkedList<T>
    where
        Iter: Iterator<Item = T>,
    {
        let mut p: *mut LinkedList<T> = ptr::null_mut();
        let mut root: *mut LinkedList<T> = ptr::null_mut();
        let mut temp_lst = vec![];
        for item in iter {
            let mut temp = Box::new(LinkedList {
                value: item,
                next: ptr::null_mut(),
            });
            if !p.is_null() {
                unsafe {
                    (*p).next = &mut (*temp);
                }
            }
            p = &mut (*temp);
            temp_lst.push(temp);
            //println!("{:?}", temp_lst);
            println!("{}", p as usize);
            if root.is_null() {
                root = p;
            }
        }

        unsafe {
            (*root).print_list();
        }

        return root;
    }
}

impl<T> DebuggableList for LinkedList<T>
where
    T: std::fmt::Display + std::fmt::Debug,
{
    fn print_list(&mut self) {
        let mut p: *mut LinkedList<T> = &mut *self;
        while !p.is_null() {
            unsafe {
                print!("{} ", (*p).value);
                p = (*p).next;
            }
        }
    }
}

// impl Config {
//     pub fn new(args: Vec<String>) -> Result<Config, &'static str> {
//         if args.len() < 1 {
//             return Err("not enough arguments");
//         }
//         //let query = args[1].clone();
//         Ok(Config {})
//     }
// }

#[test]
pub fn run() -> Result<(), Box<dyn Error>> {
    let data = vec![11, 77, 65, 22, 33];
    let mut p = LinkedList::create(data.iter());
    //unsafe {
    //    (*p).print_list();
    //}
    Ok(())
}
